//*********************************************************
//
//    Copyright (c) Microsoft. All rights reserved.
//    This code is licensed under the Apache License, Version 2.0.
//    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//********************************************************* 

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.Research.DataLayer;
using Microsoft.TridentWordAddIn.Common;
using Microsoft.TridentWordAddIn.ResourceHelper;
using TridentAPI;
using System.Collections.ObjectModel;

namespace Microsoft.TridentWordAddIn.Server
{
    public class TridentServer : ITridentServer, IDisposable
    {
        private bool disposed;
        private Connection connection;
        private TridentConnection tridentConnection;

        #region Constructor

        /// <summary>
        /// Initializes the <see cref="TridentServer"/> class.
        /// </summary>
        static TridentServer()
        {
            SR_Connection.Init();
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="TridentServer"/> class.
        /// </summary>
        public TridentServer()
        {
        }

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets the current connection.
        /// </summary>
        /// <value>The current connection.</value>
        public TridentConnection CurrentTridentConnection
        {
            get
            {
                return this.tridentConnection;
            }
            set
            {
                this.tridentConnection = value;
                if (this.tridentConnection != null)
                {
                    if (this.connection != null)
                    {
                        this.connection.Close();
                        this.connection = null;
                    }

                    this.connection = ConnectionHelper.GetServerConnection(this.tridentConnection);
                }
                else
                {
                    if (this.connection != null)
                    {
                        this.connection.Close();
                        this.connection = null;
                    }
                }
            }
        }

        /// <summary>
        /// Gets the jobs.
        /// </summary>
        /// <returns>List<WorkflowJob></returns>
        public List<WorkflowJob> Jobs
        {
            get
            {
                if (this.Connection == null)
                {
                    throw new ConnectionFailedException(ResourceFetcher.GetString("NoConnection"));
                }

                List<WorkflowJob> jobList = new List<WorkflowJob>();
                try
                {
                    Collection<Job> jobs = Job.CommonSearches.GetCompletedJobs(this.Connection, null);
                    if (jobs != null)
                    {
                        foreach (Job job in jobs)
                        {
                            if (job.Status == JobStatus.Completed)
                            {
                                WorkflowJob workflowJob = ServerHelper.ConvertToWorkflowJob(job);
                                workflowJob.Outputs = this.GetJobOutputs(job);
                                workflowJob.Parameters = this.GetJobParameter(job);
                                jobList.Add(workflowJob);
                            }
                        }
                    }
                }

                catch (BackendStorageException ex)
                {
                    throw new DatabaseException("Invalid database. Please selected the valid Trident database.", ex.InnerException);
                }
                catch (RecordNotFoundException)
                {
                }

                return jobList;
            }
        }

        /// <summary>
        /// Gets all tasks.
        /// </summary>
        /// <value>The workflows.</value>
        /// <returns>TaskCollection</returns>
        public List<Workflow> Workflows
        {
            get
            {
                if (this.Connection == null)
                {
                    throw new ConnectionFailedException(ResourceFetcher.GetString("NoConnection"));
                }

                List<Workflow> workflowList = new List<Workflow>();
                lock (this.connection)
                {
                    try
                    {
                        Collection<Activity> activities = Activity.CommonSearches.GetAllWorkflows(this.Connection, null);
                        if (activities != null)
                        {
                            foreach (Activity activity in activities)
                            {
                                if (!activity.IsDeleted &&
                                    (!activity.VersionLabel.IsNullOrEmpty() || activity.IsLatestVersion()))
                                {
                                    Workflow workflow = new Workflow();
                                    workflow.Id = (activity as IObject).ID;
                                    workflow.Name = activity.Name;
                                    workflow.DisplayName = activity.DisplayName;
                                    workflow.Description = activity.Description;
                                    workflow.Activities = GetWorkflowActivities(activity.Children);
                                    workflow.Parameters = GetWorkflowParameters(activity);
                                    workflowList.Add(workflow);
                                }
                            }
                        }
                    }
                    catch (BackendStorageException ex)
                    {
                        throw new DatabaseException("Invalid database. Please selected the valid Trident database.", ex.InnerException);
                    }
                    catch (RecordNotFoundException)
                    {

                    }
                }

                return workflowList;
            }
        }

        /// <summary>
        /// Gets the connection.
        /// </summary>
        /// <value>The connection.</value>
        private Connection Connection
        {
            get
            {
                if (this.connection == null)
                {
                    return null;
                }

                if (!this.connection.Alive)
                {
                    this.connection.Open();
                }

                return this.connection;
            }
        }

        /// <summary>
        /// Gets the trident machines.
        /// </summary>
        /// <value></value>
        /// <returns>List of string</returns>
        public List<string> Machines
        {
            get
            {
                List<string> result = new List<string>();
                if (this.Connection == null)
                {
                    return result;
                }

                try
                {
                    Collection<Machine> machines = Machine.CommonSearches.GetOnlineMachines(this.Connection, true);
                    if (null != machines)
                    {
                        foreach (Machine machine in machines)
                        {
                            if (!machine.IsDeleted)
                            {
                                result.Add(machine.Name);
                            }
                        }
                    }
                }
                catch (BackendStorageException)
                {

                }
                catch (RecordNotFoundException)
                {
                }

                return result.Distinct().ToList();
            }
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// Tests the connection.
        /// </summary>
        /// <param name="connection">The connection.</param>
        /// <param name="exception">The exception.</param>
        /// <returns>bool</returns>
        public static bool TestConnection(TridentConnection connection, ref ConnectionFailedException exception)
        {
            bool success = false;
            try
            {
                success = Ping(connection, ref exception);
            }
            catch (Exception)
            {
                success = false;
            }

            return success;
        }

        /// <summary>
        /// Gets the job by id.
        /// </summary>
        /// <param name="jobId">The job id.</param>
        /// <returns>WorkflowJob</returns>
        public WorkflowJob GetJobById(Guid jobId)
        {
            Job job = Job.Load(jobId, this.Connection);
            WorkflowJob workflowJob = ServerHelper.ConvertToWorkflowJob(job);
            workflowJob.Outputs = this.GetJobOutputs(job);
            workflowJob.Parameters = this.GetJobParameter(job);

            return workflowJob;
        }

        /// <summary>
        /// Determines whether [is workflow exists] [the specified workflow id].
        /// </summary>
        /// <param name="workflowId">The workflow id.</param>
        /// <returns>
        /// 	<c>true</c> if [is workflow exists] [the specified workflow id]; otherwise, <c>false</c>.
        /// </returns>
        public bool IsWorkflowExists(Guid workflowId)
        {
            try
            {
                Activity activity = Activity.Load(workflowId, this.Connection);
                if (activity != null)
                {
                    return true;
                }
            }
            catch (BackendStorageException ex)
            {
                throw new DatabaseException("Invalid connection. Please check the connection configuration.", ex.InnerException);
            }
            catch (RecordNotFoundException)
            {
            }

            return false;
        }

        /// <summary>
        /// Gets the name of the work flow by.
        /// </summary>
        /// <param name="workflowName">Name of the workflow.</param>
        /// <returns>Workflow</returns>
        public Workflow GetWorkflowById(Guid workflowId)
        {
            if (this.Connection == null)
            {
                throw new ConnectionFailedException(ResourceFetcher.GetString("NoConnection"));
            }

            Workflow workflow = new Workflow();
            Activity activity = Activity.Load(workflowId, this.Connection);

            workflow.Id = (activity as IObject).ID;
            workflow.Name = activity.Name;
            workflow.Description = activity.Description;
            workflow.Activities = GetWorkflowActivities(activity.Children);
            workflow.Parameters = GetWorkflowParameters(activity);
            return workflow;
        }

        /// <summary>
        /// Gets the job ouput.
        /// </summary>
        /// <param name="outputId">The output id.</param>
        /// <returns></returns>
        public JobOutput GetJobOutputById(Guid outputId)
        {
            DataProduct dataProduct = DataProduct.Load(outputId, this.Connection);
            JobOutput jobOutput = ServerHelper.ConvertToJobOutput(dataProduct);
            return jobOutput;
        }

        /// <summary>
        /// Gets the job ouput.
        /// </summary>
        /// <param name="jobId">The job id.</param>
        /// <returns></returns>
        public JobOutputCollection GetJobOutputs(Guid jobId)
        {
            if (this.Connection == null)
            {
                throw new ConnectionFailedException(ResourceFetcher.GetString("NoConnection"));
            }

            JobOutputCollection jobOutputCollection = new JobOutputCollection();
            try
            {
                Job job = Job.Load(jobId, this.Connection);
                InstanceAPI instance = new InstanceAPI(this.Connection);

                // Get Workflow Outputs
                List<DataProduct> outputs = instance.GetWorkflowOutputs(job);
                foreach (DataProduct dataProduct in outputs)
                {
                    JobOutput jobOutput = ServerHelper.ConvertToJobOutput(dataProduct);
                    jobOutputCollection.Add(jobOutput);
                }

                // Get DataProducts
                outputs = instance.GetDataProducts(job);
                foreach (DataProduct dataProduct in outputs)
                {
                    JobOutput jobOutput = ServerHelper.ConvertToJobOutput(dataProduct);
                    jobOutputCollection.Add(jobOutput);
                }
            }
            catch (RecordNotFoundException)
            {
            }

            return jobOutputCollection;
        }

        /// <summary>
        /// Checks the job status.
        /// </summary>
        /// <param name="jobId">The job id.</param>
        /// <returns>WorkflowJobStatus</returns>
        public WorkflowJobStatus CheckJobStatus(Guid jobId)
        {
            Job job = Job.Load(jobId, this.Connection);
            return ServerHelper.ConvertToWorkflowJobStatus(job.Status);
        }

        /// <summary>
        /// Checks the job status.
        /// </summary>
        /// <param name="jobId">The job id.</param>
        /// <returns>WorkflowJobStatus</returns>
        public string JobState(Guid jobId, out bool isRunning)
        {
            if (this.Connection == null)
            {
                throw new ConnectionFailedException(ResourceFetcher.GetString("NoConnection"));
            }

            isRunning = false;
            Job job = Job.Load(jobId, this.Connection);
            if (job.Status != JobStatus.Aborted && job.Status != JobStatus.Completed)
            {
                isRunning = true;
            }

            return job.Status.ToString();
        }

        /// <summary>
        /// Downloads the package.
        /// </summary>
        /// <param name="workflowId">The workflow id.</param>
        /// <returns>MemoryStream</returns>
        public MemoryStream DownloadPackage(Guid workflowId)
        {
            string filePath = FileHelper.CreateTemporaryFileName(string.Empty, string.Empty);
            try
            {
                this.ExportPackage(workflowId, filePath);
                return StreamHelper.GetMemoryStream(filePath);
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                FileHelper.DeleteFile(filePath);
            }
        }

        /// <summary>
        /// Downloads the package.
        /// </summary>
        /// <param name="workflowId"></param>
        /// <param name="filePath">The file path.</param>
        public void ExportPackage(Guid workflowId, string filePath)
        {
            if (this.Connection == null)
            {
                throw new ConnectionFailedException(ResourceFetcher.GetString("NoConnection"));
            }

            OPCConnection opcConnection = null;
            try
            {
                Activity activity = Activity.Load(workflowId, this.Connection);
                opcConnection = OPCConnection.Create(filePath);
                opcConnection.Open();
                activity.ExportToPackage(this.Connection, opcConnection);
                opcConnection.Close();
            }
            catch (BackendStorageException ex)
            {
                throw new DatabaseException("Export package failed. Invalid connection, please check the configuration.", ex.InnerException);
            }
            catch (RecordNotFoundException ex)
            {
                throw new NoRecordFoundException(ex.Message, ex.InnerException);
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                if (opcConnection != null && opcConnection.Alive)
                {
                    opcConnection.Close();
                }
            }
        }

        /// <summary>
        /// Runs the workflow.
        /// </summary>
        /// <param name="rerunInformation">The rerun information.</param>
        /// <returns>Guid</returns>
        public Guid RunWorkflow(RerunWorkflowInformation rerunWorkflowParam)
        {
            if (this.Connection == null)
            {
                throw new ConnectionFailedException(ResourceFetcher.GetString("NoConnection"));
            }

            try
            {
                Activity workflow = Activity.Load(rerunWorkflowParam.Workflow.Id, this.Connection);
                Machine.ISearch search = Machine.ISearch.Create();
                search.Query = Machine.ISearch.AND(
                                                Machine.ISearch.Name(StringField.Condition.Equals, rerunWorkflowParam.MachineName),
                                                Machine.ISearch.IsInteractiveExecution(BooleanField.Condition.Equals, true)
                                            );
                List<Machine> machine = Machine.Search(search, this.Connection);
                if ((0 == machine.Count) &&
                   (!workflow.IsInteractive))
                {
                    search.Query = Machine.ISearch.AND(
                                               Machine.ISearch.Name(StringField.Condition.Equals, rerunWorkflowParam.MachineName),
                                               Machine.ISearch.IsInteractiveExecution(BooleanField.Condition.Equals, false)
                                           );
                    machine = Machine.Search(search, this.Connection);
                }

                InstanceAPI instance = new InstanceAPI(this.Connection);
                Job job = instance.CreateJob(rerunWorkflowParam.JobName, machine[0], workflow);
                if (job != null)
                {
                    List<WorkflowParameter> workflowParameters = rerunWorkflowParam.WorkflowParameters;
                    List<ParameterAssignment> requiredParams = instance.GetWorkflowRequiredParameters(workflow);

                    object value = "";
                    foreach (ParameterAssignment param in requiredParams)
                    {
                        foreach (WorkflowParameter workflowParam in workflowParameters)
                        {
                            if (param.ActivityParameter.Name.CompareIgnoreCase(workflowParam.Name) &&
                                param.ActivityParameter.Activity.Name.CompareIgnoreCase(workflowParam.BelongsToActivity))
                            {
                                if (param.ActivityParameter.Direction == DirectionType.Output && workflowParam.Value != null)
                                {
                                    param.Type = workflowParam.Value.ToString();
                                }

                                value = workflowParam.Value;
                                break;
                            }
                        }

                        try
                        {
                            instance.CreateActivityInstanceParameters(job, param, value);
                        }
                        catch (Exception ex)
                        {
                            if (!ex.Message.ContainsIgnoreCase("Could not load custom type initializer.Could not load file or assembly 'Microsoft.Practices.EnterpriseLibrary.Logging"))
                            {
                                throw ex;
                            }
                        }
                    }

                    return (job as IObject).ID;
                }
            }
            catch (RecordNotFoundException ex)
            {
                throw new NoRecordFoundException(ex.Message, ex.InnerException);
            }

            return Guid.Empty;
        }

        /// <summary>
        /// Abort the currently executing job
        /// </summary>
        public void TerminateJob(Guid jobId)
        {
            Job job = Job.Load(jobId, this.Connection);
            if (job.Status == JobStatus.Waiting)
            {
                job.Status = JobStatus.Aborted;
            }
            else
            {
                job.Status = JobStatus.StopPending;
            }

            job.Save();
        }

        /// <summary>
        /// Determines whether [is machine online] [the specified machine name].
        /// </summary>
        /// <param name="machineName">Name of the machine.</param>
        /// <returns>
        /// 	<c>true</c> if [is machine online] [the specified machine name]; otherwise, <c>false</c>.
        /// </returns>
        public bool IsMachineOnline(string machineName)
        {
            if (this.Connection == null)
            {
                throw new ConnectionFailedException(ResourceFetcher.GetString("NoConnection"));
            }

            List<string> result = new List<string>();
            try
            {
                Collection<Machine> machines = Machine.CommonSearches.GetMachineByName(this.Connection, true, machineName);
                if (null != machines)
                {
                    foreach (Machine machine in machines)
                    {
                        if (!machine.IsDeleted && machine.Availability == ExecutorAvailabiltiy.Online)
                        {
                            return true;
                        }
                    }
                }
            }
            catch (BackendStorageException)
            {

            }
            catch (RecordNotFoundException)
            {
            }

            return false;
        }

        /// <summary>
        /// Determines whether [is machine intractive] [the specified machine name].
        /// </summary>
        /// <param name="machineName">Name of the machine.</param>
        /// <returns>
        /// 	<c>true</c> if [is machine intractive] [the specified machine name]; otherwise, <c>false</c>.
        /// </returns>
        public bool IsMachineIntractive(string machineName)
        {
            if (this.Connection == null)
            {
                throw new ConnectionFailedException(ResourceFetcher.GetString("NoConnection"));
            }
            Machine.ISearch search = Machine.ISearch.Create();
            search.Query = Machine.ISearch.AND(
                                                Machine.ISearch.Name(StringField.Condition.Equals, machineName),
                                                Machine.ISearch.IsInteractiveExecution(BooleanField.Condition.Equals, true)
                                            );
            List<Machine> machine = Machine.Search(search, this.Connection);
            return (machine.Count > 0);
        }

        /// <summary>
        /// Determines whether [is workflow deleted] [the specified workflow id].
        /// </summary>
        /// <param name="workflowId">The workflow id.</param>
        /// <returns>
        /// 	<c>true</c> if [is workflow deleted] [the specified workflow id]; otherwise, <c>false</c>.
        /// </returns>
        public bool IsWorkflowDeleted(Guid workflowId)
        {
            if (this.Connection == null)
            {
                throw new ConnectionFailedException(ResourceFetcher.GetString("NoConnection"));
            }

            try
            {
                Activity activity = Activity.Load(workflowId, this.Connection);
                return activity.IsDeleted;
            }
            catch (BackendStorageException)
            {

            }
            catch (RecordNotFoundException)
            {
            }

            return true;
        }

        /// <summary>
        /// Determines whether [is workflow intractive] [the specified workflow id].
        /// </summary>
        /// <param name="workflowId">The workflow id.</param>
        /// <returns>
        /// 	<c>true</c> if [is workflow intractive] [the specified workflow id]; otherwise, <c>false</c>.
        /// </returns>
        public bool IsWorkflowIntractive(Guid workflowId)
        {
            if (this.Connection == null)
            {
                throw new ConnectionFailedException(ResourceFetcher.GetString("NoConnection"));
            }

            try
            {
                Activity activity = Activity.Load(workflowId, this.Connection);
                return activity.IsInteractive;
            }
            catch (BackendStorageException)
            {

            }
            catch (RecordNotFoundException)
            {
            }

            return true;
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// Pings the specified conn.
        /// </summary>
        /// <param name="connection">The connection.</param>
        /// <param name="connException">The conn exception.</param>
        /// <returns>bool</returns>
        private static bool Ping(TridentConnection connection, ref ConnectionFailedException connException)
        {
            bool success = false;
            IConnMgrInfoParams connectionParams;
            BackendStorageException backendStorageException = null;
            try
            {
                switch (connection.ConnectionType)
                {
                    case ConnectionType.Sql:
                        connectionParams = ConnectionHelper.GetSqlParameters(connection.Name, connection.SqlParameters);
                        SQLConnectionParameters.Helper sqlConnectionHelper = new SQLConnectionParameters.Helper();
                        success = sqlConnectionHelper.TestConnection(connectionParams, out backendStorageException);
                        break;
                    //case ConnectionType.WebService:
                    //    connectionParams = ConnectionHelper.GetWebServiceParameters(connection.Name, connection.WebServiceParameters);
                    //    WSConnectionParameters.Helper webServiceHelper = new WSConnectionParameters.Helper();
                    //    success = webServiceHelper.TestConnection(connectionParams, out backendStorageException);
                    //    break;
                }

                if (backendStorageException != null)
                {
                    connException = new ConnectionFailedException(backendStorageException.Message, backendStorageException.InnerException);
                }
            }
            catch (Exception ex)
            {
                connException = new ConnectionFailedException(ex.Message, ex.InnerException);
            }

            return success;
        }

        /// <summary>
        /// Gets the job outputs.
        /// </summary>
        /// <param name="job">The job.</param>
        /// <returns>JobOutputCollection</returns>
        private ShallowJobOutputCollection GetJobOutputs(Job job)
        {
            ShallowJobOutputCollection jobOutputCollection = new ShallowJobOutputCollection();
            InstanceAPI instance = new InstanceAPI(this.Connection);

            // Get Workflow Outputs
            List<DataProduct> outputs = instance.GetWorkflowOutputs(job);
            foreach (DataProduct dataProduct in outputs)
            {
                ShallowJobOutput jobOutput = ServerHelper.ConvertToShallowOutput(dataProduct);
                jobOutputCollection.Add(jobOutput);
            }

            // Get DataProducts
            outputs = instance.GetDataProducts(job);
            foreach (DataProduct dataProduct in outputs)
            {
                ShallowJobOutput jobOutput = ServerHelper.ConvertToShallowOutput(dataProduct);
                jobOutputCollection.Add(jobOutput);
            }

            return jobOutputCollection;
        }

        /// <summary>
        /// Gets the activity parameters.
        /// </summary>
        /// <param name="parameters">The parameters.</param>
        /// <returns>ParametersCollection</returns>
        private static List<WorkflowParameter> GetActivityParameters(ActivityParameterCollection<Activity> parameters)
        {
            List<WorkflowParameter> parametersCollection = new List<WorkflowParameter>();
            foreach (ActivityParameter parameter in parameters)
            {
                WorkflowParameter param = new WorkflowParameter();
                param.Name = parameter.Name;
                param.Label = parameter.Label;
                param.IsInput = parameter.Direction == DirectionType.Input ? true : false;
                param.Type = parameter.Type;
                param.BelongsToActivity = parameter.Activity.Name;

                parametersCollection.Add(param);
            }

            return parametersCollection;
        }

        /// <summary>
        /// Gets the job parameter.
        /// </summary>
        /// <param name="job">The job.</param>
        /// <returns>List of JobParameter</returns>
        private List<JobParameter> GetJobParameter(Job job)
        {
            List<JobParameter> jobParameters = new List<JobParameter>();
            foreach (ActivityInstanceParameter param in job.ActivityInstances[0].ActivityInstanceParameters)
            {
                JobParameter jobParam = ParameterHelper.ConvertToJobParameter(param);
                jobParameters.Add(jobParam);
            }

            return jobParameters;
        }

        /// <summary>
        /// Gets the workflow parameters.
        /// </summary>
        /// <param name="workflow">The workflow.</param>
        /// <returns></returns>
        private List<WorkflowParameter> GetWorkflowParameters(Activity workflow)
        {
            List<WorkflowParameter> result = new List<WorkflowParameter>();
            InstanceAPI instance = new InstanceAPI(this.Connection);
            List<ParameterAssignment> requiredParams = instance.GetWorkflowRequiredParameters(workflow);
            foreach (ParameterAssignment parameter in requiredParams)
            {
                WorkflowParameter param = ParameterHelper.ConvertToWorkflowParameter(parameter);
                result.Add(param);
            }

            return result;
        }

        /// <summary>
        /// Gets the workflow activities.
        /// </summary>
        /// <param name="children">The children.</param>
        /// <returns>ActivityCollection</returns>
        private static List<WorkflowActivity> GetWorkflowActivities(List<ActivitySequence> children)
        {
            List<WorkflowActivity> activityCollection = new List<WorkflowActivity>();
            foreach (ActivitySequence activity in children)
            {
                if (activity.Activity.IsComposite)
                {
                    activityCollection.AddRange(GetWorkflowActivities(activity.Children));
                }
                else
                {
                    WorkflowActivity workflowActivity = new WorkflowActivity();
                    workflowActivity.Id = (activity as IObject).ID;
                    workflowActivity.Name = activity.Activity.Name;
                    string label = activity.Activity.Label;
                    workflowActivity.Label = label.IsNullOrEmpty() ? workflowActivity.Name : label;
                    workflowActivity.Description = activity.Activity.Description;
                    workflowActivity.Parameters = GetActivityParameters(activity.Activity.ActivityParameters);
                    activityCollection.Add(workflowActivity);
                }
            }

            return activityCollection;
        }

        #endregion

        #region IDisposable Members

        public void Dispose()
        {
            this.Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// Disposes the specified the privately held resources.
        /// </summary>
        /// <param name="disposing">if set to <c>true</c> disposes resources.</param>
        private void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    if (this.connection != null)
                    {
                        this.connection.Close();
                        this.connection = null;
                    }
                }
            }

            this.disposed = true;
        }

        #endregion
    }
}
